# vim:ts=4:sw=4:noet:
""" Update Checker """

from c.base.version import InfoStrings
import urllib2
from xml.dom.minidom import parse
import threading
import logging
import time
import platform

class UpdaterException(Exception):
	pass

class Update:
	def __init__(self):
		self.sparkle = {}

	def __repr__(self):
		r = "<update:"
		for d in dir(self):
			if "__" not in d:
				r += " %s:'%s'" % (d, getattr(self,d))
		r += ">"
		return r

class Version:
	def __init__(self, vstring):
		self.version = vstring.split(".")

	def __cmp__(self, other):
		if other.__class__!=self.__class__:
			return 1
		for i in range(min(len(self.version), len(other.version))):
			if self.version[i] > other.version[i]:
				return 1
			elif self.version[i] < other.version[i]:
				return -1
		if len(self.version) == len(other.version):
			return 0
		elif len(self.version) > len(other.version):
			return 1
		else:
			return -1

	def __repr__(self):
		return '.'.join(self.version)

class Updater:
	def __init__(self, currentVersion, updateAvailableCallback):
		self.appcastUrl = InfoStrings["urlAppcast"]
		self.currentVersion = Version(currentVersion)
		self.updateAvailableCallback = updateAvailableCallback

	def check(self):
		self.thread = threading.Thread(
		None, 
		self.__check)
		self.thread.start()

	def __check(self):
		time.sleep(1)
		try:
			url = urllib2.urlopen(self.appcastUrl)
			dom = parse(url)
			url.close()
		except Exception,e:
			logging.warn("Update check failed - couldn't connect, or invalid data: %s" % e)
			return
		channels = dom.getElementsByTagName("channel")
		if len(channels)!=1:
			raise UpdaterException("too many channels")
		self.updates = []
		for item in channels[0].getElementsByTagName("item"):
			update = Update()
			children = [n for n in item.childNodes if n.nodeType == n.ELEMENT_NODE]
			for c in children:
				cname = c.tagName
				cattrs = c.attributes
				cchild = c.childNodes
				if cname == "title":
					update.title = cchild[0].data
				elif cname == "pubDate":
					update.pubdate = cchild[0].data
				elif cname == "enclosure":
					update.url = cattrs["url"].value
					update.sparkle["version"] = Version(cattrs["sparkle:version"].value)
					update.sparkle["md5"] = cattrs["sparkle:md5Sum"].value
					update.sparkle["ostype"] = cattrs["sparkle:ostype"].value
					update.type = cattrs["type"].value
					update.length = cattrs["length"].value
				elif cname[:8] == "sparkle:":
					update.sparkle[cname[8:]] = cchild[0].data
				else:
					raise UpdaterException("unknown item %s" % cname)
			self.updates.append(update)
		# check updates
		latestVersion = 0
		newUpdate = None
		myos = "win"
		if platform.system()=="Darwin":
			myos = "mac"
		for update in self.updates:
			if update.sparkle["version"] > latestVersion and myos==update.sparkle["ostype"]:
				latestVersion = update.sparkle["version"]
				newUpdate = update

		if latestVersion > self.currentVersion:
			self.updateAvailableCallback(newUpdate)
